// * JS 引擎在值 “可达” 和 可能被使用时，会将其保持在内存中，不会被垃圾回收机制回收。

// ********************************************************************************************

// * WeakMap 和 Map 的第一个不同点就是，WeakMap 的键必须是对象，而不能是原始值。
let weakMap = new WeakMap()
let obj = {}
weakMap.set(obj, 'ok') // 正常，对象作为键
// weakMap.set(1, 'not ok') // 报错，键必须是对象

// * 如果对象键被清除了,并且没有其他对这个对象的引用，WeakMap 也会自动清除对应的键值对。
let john = { name: 'John' }
let weakMap2 = new WeakMap()
weakMap2.set(john, '...')
john = null // 对象引用被清除（会从内存在被删除）
console.log(weakMap2.get(john)) // undefined

// * WeakMap 只有以下方法：
// weakMap.get(key) // 返回 key 对应的 value，如果不存在则返回 undefined
// weakMap.set(key, value) // 设置 key 对应的 value
// weakMap.delete(key) // 删除 key 对应的 value
// weakMap.has(key) // 判断 key 是否存在

// ********************************************************************************************

// * WeakSet 与 set 类似，但是只能向 WeakSet 添加对象（而不能是原始值）。
// * WeakSet 只支持：add、has 和 delete 方法。
// * 存入的对象，如果没有其他引用指向它，则会在垃圾回收时自动删除。

// 例子：
let weakSet = new WeakSet()

let john1 = { name: 'John' }
let pete = { name: 'Pete' }
let mary = { name: 'Mary' }

weakSet.add(john1).add(pete).add(mary).add(mary) // 现在 weakSet 包含 3 个对象

console.log(weakSet.has(john1)) // true
console.log(weakSet.has(pete)) // true
console.log(weakSet.has(mary)) // true

john1 = null // 引用 john1 被清除

// 将被自动清理(即自动清除其中已失效的值 john1)
console.log(weakSet.has(john1)) // false
